package com.example.demo.gateway.service;

import cn.hutool.core.bean.BeanUtil;
import com.example.demo.gateway.entity.GatewayUpstream;
import com.example.demo.gateway.event.RefreshUpstreamEvent;
import com.example.demo.gateway.repository.GatewayUpstreamRepository;
import com.example.demo.gateway.req.GatewayUpstreamReq;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.validation.Valid;

/**
 * @author Itachi is.xianglei@gmail.com
 * @Date 2020-05-22 22:00
 */
@Slf4j
@Service
public class GatewayUpstreamService implements ApplicationEventPublisherAware {

    @Autowired
    private GatewayUpstreamRepository gatewayUpstreamRepository;

    private ApplicationEventPublisher applicationEventPublisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    /**
     * 增加Upstream
     *
     * @param
     * @param req
     * @return
     */
    public Mono<GatewayUpstream> add(@Valid GatewayUpstreamReq req) {

        GatewayUpstream entity = new GatewayUpstream();
        BeanUtil.copyProperties(req, entity);
        return gatewayUpstreamRepository.save(entity).
                doOnSuccess(gatewayUpstream -> {
                    log.info("gatewayUpstream:{}", gatewayUpstream);
                    applicationEventPublisher.publishEvent(new RefreshUpstreamEvent(this));
                });
    }

    /**
     * 更新
     *
     * @param
     * @return
     */
    public Mono<GatewayUpstream> update(GatewayUpstreamReq req) {
        GatewayUpstream entity = new GatewayUpstream();
        BeanUtil.copyProperties(req, entity);
        return gatewayUpstreamRepository.save(entity).doOnSuccess(gatewayUpstream -> {
            log.info("gatewayUpstream:{}", gatewayUpstream);
            applicationEventPublisher.publishEvent(new RefreshUpstreamEvent(this));
        });
    }

    /**
     * 删除
     *
     * @param id
     * @return
     */
    public Mono<ResponseEntity<Void>> deleteById(Long id) {
        return gatewayUpstreamRepository.findById(id)
                //当你需要操作数据并返回一个mono使用flatmap
                // 如果不操作数据仅作转换数据，使用map
                .flatMap(entity -> gatewayUpstreamRepository.delete(entity))
                .then(Mono.just(new ResponseEntity<Void>(HttpStatus.OK)))
                .defaultIfEmpty(new ResponseEntity<Void>(HttpStatus.NOT_FOUND));

    }

    /**
     * 查询所有Upstream
     *
     * @param
     * @return
     */
    public Flux<GatewayUpstream> findAll() {
        return gatewayUpstreamRepository.findAll();
    }

    public Mono<GatewayUpstream> findById(Long id) {
        return gatewayUpstreamRepository.findById(id);
    }

    public Mono<Void> refresh() {
        applicationEventPublisher.publishEvent(new RefreshUpstreamEvent(this));
        return Mono.empty();
    }

    public Flux<GatewayUpstream> findPage(int pageNo, int pageSize) {
        int start = (pageNo - 1) * pageSize;
        return gatewayUpstreamRepository.findPage(start, pageSize);
    }

    public Mono<Long> count() {
        return gatewayUpstreamRepository.count();
    }

}
